package com.to.aboomy.banner;

import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.Image;
import ohos.agp.components.PageSlider;
import ohos.agp.components.PageSliderProvider;
import ohos.agp.render.Canvas;
import ohos.app.Context;
import ohos.multimodalinput.event.MmiPoint;
import ohos.multimodalinput.event.TouchEvent;

import java.util.LinkedHashMap;
import java.util.List;

/**
 * @since 2021-07-20
 */
public class BannerViewPager extends PageSlider implements PageSlider.PageChangedListener,
        Component.TouchEventListener, Component.DrawTask {
    // 根据子容器的hashCode存入数据索引
    private final LinkedHashMap<Integer, String> mapContainer = new LinkedHashMap<>();
    // 是否开启日志打印
    private boolean isInfoPrint = true;

    // 方向布局，组容器
    private DirectionalLayout groupContainer;

    // 当前容器的索引
    private int currentContainerIndex = 0;

    // 新的容器的索引（用于更新当前容器索引）
    private int newCurrentContainerIndex = 0;

    // 按下x轴坐标
    private float downX;

    // 是否调用setCurrentPage方法，首位到末位
    private boolean isStartToEnd = false;

    // 是否调用setCurrentPage方法，末位到首位
    private boolean isEndToStart = false;

    // 是否第一次滑动
    private boolean isFirstSlide = true;

    // 是否滑入上一页
    private boolean isSlidePreviousPage = false;

    // 是否滑入下一页
    private boolean isSlideNextPage = false;

    // 页面滑动状态改变：0空闲、1拖动、2滑动
    private int slideState = 0;

    // 是否初始化当前容器索引
    private boolean isInitCurrentContainerIndex = false;

    // 是否初始化后，重新设置setCurrentPage
    private boolean isSetCurrentPage = false;

    // 旧的当前页面
    private int oldCurrentPage = 0;

    // 页面间距
    private int pageMargin = 0;

    // 页面切换动画
    private PageTransformer pageTransformer;

    // 页面点击事件
    private PageClickedListener pageClickedListener;

    // 页面选中事件
    private PageSelectedListener pageSelectedListener;
    /**
     * 设置圆角
     */
    private int mCornerRadius = 0;

    // 页面内间距
    private int padding = 0;

    public BannerViewPager(Context context) {
        this(context, null);
    }

    public BannerViewPager(Context context, AttrSet attrSet) {
        this(context, attrSet, "");
    }

    public BannerViewPager(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        addDrawTask(this);
        setTouchEventListener(this);
        addPageChangedListener(this);
    }

    public void setInfoPrint(boolean infoPrint) {
        isInfoPrint = infoPrint;
    }



    /**
     * 设置界面切换动画
     *
     * @param pageTransformer 界面切换动画
     */
    public void setPageTransformer(PageTransformer pageTransformer) {
        this.pageTransformer = pageTransformer;
    }

    /**
     * 设置页面点击事件
     *
     * @param pageClickedListener 页面点击事件
     */
    public void setPageClickedListener(PageClickedListener pageClickedListener) {
        this.pageClickedListener = pageClickedListener;
    }

    /**
     * 设置页面选中事件
     *
     * @param pageSelectedListener 页面选中事件
     */
    public void setPageSelectedListener(PageSelectedListener pageSelectedListener) {
        this.pageSelectedListener = pageSelectedListener;
    }

    /**
     * 设置数据
     *
     * @param dataList 数据集合
     */
    public void setData(List<Integer> dataList) {
        setProvider(new PageSliderProvider() {
            @Override
            public int getCount() {
                return dataList.size();
            }

            @Override
            public Object createPageInContainer(ComponentContainer container, int position) {
                Image image = null;
                if(holderCreator == null){
                    image = new Image(getContext());
                    ComponentContainer.LayoutConfig layoutConfig = new ComponentContainer.LayoutConfig(
                            ComponentContainer.LayoutConfig.MATCH_PARENT, ComponentContainer.LayoutConfig.MATCH_PARENT);
                    image.setLayoutConfig(layoutConfig);
                    image.setScaleMode(Image.ScaleMode.STRETCH);
                    image.setPixelMap(dataList.get(position));

                }else{
                    image = (Image) holderCreator.createView(getContext(),dataList.get(position),position);
                    ComponentContainer.LayoutConfig layoutConfig = new ComponentContainer.LayoutConfig(
                            ComponentContainer.LayoutConfig.MATCH_PARENT, ComponentContainer.LayoutConfig.MATCH_PARENT);
                    image.setLayoutConfig(layoutConfig);
                    image.setScaleMode(Image.ScaleMode.STRETCH);
                }
                if(padding == 0){
                    image.setMarginsLeftAndRight(pageMargin / 2, pageMargin / 2);
                }else{
                    image.setMarginsLeftAndRight(padding, padding);
                }
                image.setCornerRadius(mCornerRadius);
                container.addComponent(image);
                mapContainer.put(container.hashCode(), position + "，" + container);
                System.out.println("========添加========" + position + "，" + container);
                return image;
            }

            @Override
            public void destroyPageFromContainer(ComponentContainer container, int position, Object object) {
                container.removeComponent((Component) object);
            }

            @Override
            public boolean isPageMatchToObject(Component page, Object object) {
                return true;
            }
        });

    }

    public void setPageMargin(int margin, int padding) {
        this.pageMargin = Math.abs(margin);
        this.padding = padding;
        super.setPageMargin(margin);
    }

    @Override
    public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
        MmiPoint pointerPosition = touchEvent.getPointerPosition(touchEvent.getIndex());
        switch (touchEvent.getAction()) {
            case TouchEvent.PRIMARY_POINT_DOWN:
                downX = pointerPosition.getX();
                break;
            case TouchEvent.POINT_MOVE:
                isSlidePreviousPage = pointerPosition.getX() - downX > 0;
                break;
        }
        return true;
    }


    @Override
    public void onDraw(Component component, Canvas canvas) {
        if (groupContainer == null && getProvider() != null) {
            Component componentAt = getComponentAt(0);
            groupContainer = (DirectionalLayout) componentAt;
            initCurrentContainerIndex();
            setItemTransformer(0, 0);
            // 页面选中事件
            if (pageSelectedListener != null) {
                pageSelectedListener.onSelect(groupContainer.getComponentAt(newCurrentContainerIndex), getCurrentPage());
            }

            // 页面点击事件
            setPageClickedListener();
            printContainerData("onDraw");
        }
    }

    /**
     * 打印容器数据
     *
     * @param tag 标识
     */
    private void printContainerData(String tag) {
        for (int i = 0; i < groupContainer.getChildCount(); i++) {
            Component childContainer = groupContainer.getComponentAt(i);
        }
    }

    @Override
    public void setCurrentPage(int itemPos) {
        oldCurrentPage = getCurrentPage();
        isSetCurrentPage = true;
        super.setCurrentPage(itemPos);
    }

    @Override
    public void setCurrentPage(int itemPos, boolean smoothScroll) {
        oldCurrentPage = getCurrentPage();
        isSetCurrentPage = true;
        super.setCurrentPage(itemPos, smoothScroll);
    }

    /**
     * 初始化之后设置当前页数，更新容器索引
     *
     * @param itemPos 当前页数
     */
    private void setCurrentPageUpdateIndex(int itemPos) {
        if (isInitCurrentContainerIndex) {
            isStartToEnd = false;
            isEndToStart = false;
            // 传的页面和当前页面比较
            // 大于：当前容器索引+1
            // 小于：当前容器索引-1
            if (itemPos > oldCurrentPage) {
                if (oldCurrentPage == 0 && itemPos == getProvider().getCount() - 1) {
                    newCurrentContainerIndex--;
                    if (newCurrentContainerIndex < 0) {
                        newCurrentContainerIndex = groupContainer.getChildCount() - 1;
                    }
                    isStartToEnd = true;
                } else {
                    newCurrentContainerIndex++;
                    if (newCurrentContainerIndex > groupContainer.getChildCount() - 1) {
                        newCurrentContainerIndex = 0;
                    }
                }
            } else if (itemPos < oldCurrentPage) {
                if (oldCurrentPage == getProvider().getCount() - 1 && itemPos == 0) {
                    newCurrentContainerIndex++;
                    if (newCurrentContainerIndex > groupContainer.getChildCount() - 1) {
                        newCurrentContainerIndex = 0;
                    }
                    isEndToStart = true;
                } else {
                    newCurrentContainerIndex--;
                    if (newCurrentContainerIndex < 0) {
                        newCurrentContainerIndex = groupContainer.getChildCount() - 1;
                    }
                }
            }
        }
    }



    /**
     * 初始化当前容器索引
     */
    private void initCurrentContainerIndex() {
        if (groupContainer == null) {
            return;
        }
        // 当前页
        int currentPage = getCurrentPage();
        // 缓存的页数
        int cachedPages = getCachedPagesLimit();
        // 容器数量
        int containerCount = groupContainer.getChildCount();
        // 数据数量
        int dataCount = getProvider().getCount();
        // 当前容器索引
        int ccIndex = 0;

        // 是否开启了无限循环
        if (isCircularModeEnabled()) {
            // 当前页就是缓存的数量
            ccIndex = cachedPages;

            // 设置了选中页面
            if (currentPage != 0 && currentPage < dataCount) {
                if (currentPage == dataCount - 1) {
                    ccIndex = cachedPages - 1;
                } else {
                    ccIndex = cachedPages + 1;
                }
            }
        } else {
            // 未开启循环，设置选中页面
            if (currentPage != 0 && currentPage < dataCount) {
                if (currentPage < containerCount + cachedPages) {
                    ccIndex = currentPage % containerCount;

                } else if (currentPage < dataCount - cachedPages) {
                    ccIndex = cachedPages;

                } else {
                    ccIndex = cachedPages + currentPage - (dataCount - 1 - cachedPages);
                }
            }
        }
        currentContainerIndex = ccIndex;
        newCurrentContainerIndex = currentContainerIndex;
        isInitCurrentContainerIndex = true;
    }


    /**
     * 页面滑动中事件
     *
     * @param itemPos             数据索引
     * @param itemPosOffset       偏移量
     * @param itemPosOffsetPixels 偏移像素
     */
    @Override
    public void onPageSliding(int itemPos, float itemPosOffset, int itemPosOffsetPixels) {
        // 设置页面切换动画
        if (pageTransformer != null && groupContainer != null) {
            // 子容器宽度
            int childWidth = getWidth() - pageMargin;

            // （首次滑动bug）因为开启了无限循环，itemPosOffsetPixels包括了前面的缓存页面
            // 首次下一页，itemPosOffset一直为1.0 且 itemPosOffsetPixels大于容器的宽度
            // 首次上一页，itemPosOffsetPixels为正数
            if (Math.abs(itemPosOffsetPixels) > childWidth || (isFirstSlide && isSlidePreviousPage && itemPosOffsetPixels > 0)) {
                itemPosOffsetPixels = Math.abs(itemPosOffsetPixels) - childWidth * getCachedPagesLimit();
                itemPosOffset = Math.abs((float) itemPosOffsetPixels / childWidth);
            }

            // 偏移像素，正数-下一页，负数-上一页
            isSlideNextPage = itemPosOffsetPixels > 0;

            // 非滑动状态，更新当前索引
            if (slideState != 2) {
                currentContainerIndex = newCurrentContainerIndex;
            } else {
                if (isStartToEnd) {
                    isStartToEnd = false;
                    currentContainerIndex = newCurrentContainerIndex - 1;
                }

                if (isEndToStart) {
                    isEndToStart = false;
                    currentContainerIndex = newCurrentContainerIndex + 1;
                }
                isFirstSlide = false;
            }


            setItemTransformer(itemPosOffset, itemPosOffsetPixels);
        }
        if(indicationPageSliding!=null){
            System.out.println("===============onPageSliding===============itemPos="+itemPos);
            indicationPageSliding.onPageSliding(itemPos,itemPosOffset,itemPosOffsetPixels);
        }
    }

    /**
     * 加载页面切换动画
     *
     * @param offset       偏移量
     * @param offsetPixels 偏移像素
     */
    private void setItemTransformer(float offset, float offsetPixels) {
        if (pageTransformer == null) {
            return;
        }
        // 上页索引
        int previousPageIndex;
        if (currentContainerIndex - 1 < 0) {
            previousPageIndex = groupContainer.getChildCount() - 1;
        } else {
            previousPageIndex = currentContainerIndex - 1;
        }

        // 下页索引
        int nextPageIndex;
        if (currentContainerIndex + 1 > groupContainer.getChildCount() - 1) {
            nextPageIndex = 0;
        } else {
            nextPageIndex = currentContainerIndex + 1;
        }

        for (int i = 0; i < groupContainer.getChildCount(); i++) {
            Component item = groupContainer.getComponentAt(i);
            PageType pageType;
            if (previousPageIndex == i) {
                pageType = PageType.PREVIOUS;
            } else if (currentContainerIndex == i) {
                pageType = PageType.CURRENT;
            } else if (nextPageIndex == i) {
                pageType = PageType.NEXT;
            } else {
                pageType = PageType.OTHER;
            }
            pageTransformer.transformerPage(pageType, item, offset, offsetPixels);
        }
    }

    /**
     * 页面滑动状态改变
     *
     * @param state 0空闲、1拖动、2滑动
     */
    @Override
    public void onPageSlideStateChanged(int state) {
        slideState = state;
        // 非滑动状态，更新当前索引
        if (slideState != 2) {
            currentContainerIndex = newCurrentContainerIndex;
            // 页面点击事件
            setPageClickedListener();
        }

    }

    /**
     * 获取滑动状态名
     *
     * @param state 滑动状态
     * @return 滑动状态名
     */
    private String getSlideStateName(int state) {
        String stateName;
        switch (state) {
            case 0:
                stateName = "0，空闲";
                break;
            case 1:
                stateName = "1，拖动";
                break;
            default:
                stateName = "2，滑动";
                break;
        }
        return stateName;
    }

    /**
     * 选择新页面成功时回调
     *
     * @param itemPos 数据索引
     */
    @Override
    public void onPageChosen(int itemPos) {

        if (groupContainer == null) {
            isSetCurrentPage = false;
            return;
        }

        // 重新设置新的页面，更新当前容器索引
        if (isSetCurrentPage) {
            isSetCurrentPage = false;
            setCurrentPageUpdateIndex(itemPos);
        } else {
            // 手动左右滑动，更新当前容器索引
            if (isSlideNextPage) {
                newCurrentContainerIndex++;
                if (newCurrentContainerIndex > groupContainer.getChildCount() - 1) {
                    newCurrentContainerIndex = 0;
                }
            } else {
                newCurrentContainerIndex--;
                if (newCurrentContainerIndex < 0) {
                    newCurrentContainerIndex = groupContainer.getChildCount() - 1;
                }
            }
        }

        // 页面选中事件
        if (pageSelectedListener != null) {
            pageSelectedListener.onSelect(groupContainer.getComponentAt(newCurrentContainerIndex), itemPos);
        }

        // 打印容器数据
        printContainerData("onPageChosen");
    }

    /**
     * 一页三屏，页面是后面容器盖在前面容器，
     * 导致只能得到 当前容器和后面容器的点击事件
     * 设置点击事件，上页，当前页，下页
     */
    private void setPageClickedListener() {

        // 页面点击事件
        if (pageClickedListener != null) {
            // 当前页
            int itemPos = getCurrentPage();
            // 容器数量
            int containerCount = groupContainer.getChildCount();
            // 数据数量
            int dataCount = getProvider().getCount();
            // 当前容器索引
            int ccIndex = newCurrentContainerIndex;

            // 上页容器索引
            int previousPageIndex;
            if (ccIndex - 1 < 0) {
                previousPageIndex = containerCount - 1;
            } else {
                previousPageIndex = ccIndex - 1;
            }

            // 下页容器索引
            int nextPageIndex;
            if (ccIndex + 1 > containerCount - 1) {
                nextPageIndex = 0;
            } else {
                nextPageIndex = ccIndex + 1;
            }


            // 上页数据索引
            int previousItemPos;
            if (itemPos - 1 < 0) {
                previousItemPos = dataCount - 1;
            } else {
                previousItemPos = itemPos - 1;
            }

            // 下页容器索引
            int nextPageItemPos;
            if (itemPos + 1 > dataCount - 1) {
                nextPageItemPos = 0;
            } else {
                nextPageItemPos = itemPos + 1;
            }

            // 当前容器
            Component currentContainer = groupContainer.getComponentAt(ccIndex);

            // 一页三屏效果
            if (pageMargin > 0) {
                // 当前容器触摸事件
                currentContainer.setTouchEventListener(new TouchEventListener() {
                    float clickDownX = 0;

                    @Override
                    public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
                        MmiPoint pointerPosition = touchEvent.getPointerPosition(touchEvent.getIndex());
                        switch (touchEvent.getAction()) {
                            case TouchEvent.PRIMARY_POINT_DOWN:
                                clickDownX = pointerPosition.getX();
                                break;
                            case TouchEvent.PRIMARY_POINT_UP:
                                if (clickDownX == pointerPosition.getX()) {
                                    // 当前页点击
                                    if (clickDownX > pageMargin / 2f && clickDownX < getWidth() - pageMargin / 2f) {
                                        pageClickedListener.onClick(component, itemPos);
                                    } else if (clickDownX < pageMargin / 2f) {
                                        pageClickedListener.onClick(component, previousItemPos);
                                    }
                                }
                                break;
                        }
                        return true;
                    }
                });

                // 下页容器
                Component nextContainer = groupContainer.getComponentAt(nextPageIndex);
                nextContainer.setClickedListener(component -> {
                    pageClickedListener.onClick(component, nextPageItemPos);
                });
            } else {
                currentContainer.setClickedListener(component -> {
                    pageClickedListener.onClick(component, itemPos);
                });
            }
        }
    }

    /**
     * 设置圆角
     */
    public void setRornerRadius(int cornerRadius) {
        this.mCornerRadius = cornerRadius;
    }

    /**
     * 页面点击事件
     */
    public interface PageClickedListener {
        void onClick(Component component, int itemPos);
    }

    /**
     * 页面选中事件
     */
    public interface PageSelectedListener {
        void onSelect(Component component, int itemPos);
    }

    /**
     * 页面切换动画
     */
    public interface PageTransformer {
        /**
         * 页面切换动画实现
         *
         * @param pageType 页面类型：PREVIOUS、CURRENT、NEXT、OTHER
         * @param page     组件
         * @param offset   偏移量
         */
        void transformerPage(PageType pageType, Component page, float offset, float offsetPixels);
    }


    private IndicationPageSliding indicationPageSliding = null;

    /**
     * 向外暴露真实的索引值
     */
    public interface IndicationPageSliding {
        void onPageSliding(int itemPos, float itemPosOffset, int itemPosOffsetPixels);

        //用于处理背景
        void onMPageSliding(int itemPos, float itemPosOffset, int itemPosOffsetPixels);
    }

    public void setIndicationPageSliding(IndicationPageSliding indicationPageSliding) {
        this.indicationPageSliding = indicationPageSliding;
    }

    /**
     * 图片加载器
     */
    private HolderCreator holderCreator = null;

    /**
     * 设置图片加载器
     *
     * @param holderCreator 加载器
     */
    public void setHolderCreator(HolderCreator holderCreator) {
        this.holderCreator = holderCreator;
    }

    /**
     * 页面类型
     */
    public enum PageType {
        PREVIOUS,//上页
        CURRENT,//当前页
        NEXT,//下页
        OTHER,//其他
    }
}
